package com.cdks.wuxiu.api.controller;

import com.cdks.wuxiu.api.component.aliyun.CloudStorage;
import com.cdks.wuxiu.api.component.constant.Constant;
import com.cdks.wuxiu.api.component.huawei.Moderation;
import com.cdks.wuxiu.api.model.common.AuthParam;
import com.cdks.wuxiu.api.model.param.UserCallSettingParam;
import com.cdks.wuxiu.api.model.param.UserGetFocusListParam;
import com.cdks.wuxiu.api.model.param.UserGetFriendListParam;
import com.cdks.wuxiu.api.model.param.UserAuthParam;
import com.cdks.wuxiu.api.model.param.UserBlockParam;
import com.cdks.wuxiu.api.model.param.UserFocusParam;
import com.cdks.wuxiu.api.model.param.UserSetUserInfoParam;
import com.cdks.wuxiu.api.model.param.UserGetUserInfoParam;
import com.cdks.wuxiu.api.model.param.UserSetFriendParam;
import com.cdks.wuxiu.api.model.vo.UserInfoVO;
import com.cdks.wuxiu.api.service.AlbumService;
import com.cdks.wuxiu.api.service.AuthService;
import com.cdks.wuxiu.api.service.CallService;
import com.cdks.wuxiu.api.service.ChatService;
import com.cdks.wuxiu.api.service.MessageService;
import com.cdks.wuxiu.api.service.UserService;
import com.cdks.wuxiu.api.service.VideoService;
import com.cdks.wuxiu.api.service.VoiceService;
import com.cdks.wuxiu.api.util.HttpUtils;
import com.cdks.wuxiu.api.util.SmsUtils;
import com.cdks.wuxiu.api.util.TimeUtils;
import com.cdks.wuxiu.common.component.constant.ApiCodeEnum;
import com.cdks.wuxiu.common.model.api.ApiResult;
import com.cdks.wuxiu.entity.message.ChatPrivateData;
import com.cdks.wuxiu.entity.mysql.UserAlbumInfo;
import com.cdks.wuxiu.entity.mysql.UserAuthInfo;
import com.cdks.wuxiu.entity.mysql.UserBaseInfo;
import com.cdks.wuxiu.entity.mysql.UserExtendInfo;
import com.cdks.wuxiu.entity.mysql.UserFansInfo;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.temporal.ChronoUnit;
import java.util.List;

import javax.annotation.Resource;
import javax.validation.Valid;


@Api(tags = "用户")
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
    @Resource
    private UserService userService;
    @Resource
    private AlbumService albumService;
    @Resource
    private VideoService videoService;
    @Resource
    private VoiceService voiceService;
    @Resource
    private CallService callService;
    @Resource
    private AuthService authService;
    @Resource
    private ChatService chatService;
    @Resource
    private MessageService messageService;


    @ApiOperation("查询用户基本信息")
    @PostMapping("/getBaseInfo")
    public ApiResult<UserInfoVO> getBaseInfo(@RequestBody @Valid UserGetUserInfoParam param) {
        Object userInfo;
        //游客模式
        if (param.getUserId() == null)
        {
            userInfo  = userService.getUserById(param.getDestId());
        }
        else
        {
            userInfo  = userService.getUserByIdWithFocus(param.getDestId(), param.getUserId());
        }

        if (userInfo == null)
        {
            return ApiResult.failed(10, "用户信息有误");
        }

        return ApiResult.success(BeanUtil.copyProperties(userInfo, UserInfoVO.class));
    }

    @ApiOperation("查询用户详细信息")
    @PostMapping("/getDetailInfo")
    public ApiResult<Object> getDetailInfo(@RequestBody @Valid UserGetUserInfoParam param) {
        Object userInfo;
        //游客模式
        if (param.getUserId() == null)
        {
            userInfo  = userService.getUserById(param.getDestId());
        }
        else
        {
            userInfo  = userService.getUserByIdWithFocus(param.getDestId(), param.getUserId());
        }
        
        if (userInfo == null)
        {
            return ApiResult.failed(10, "用户信息有误");
        }

        JSONObject json  = new JSONObject();
        json.set("baseInfo", BeanUtil.copyProperties(userInfo, UserInfoVO.class));
        json.set("extInfo", userService.getUserExtendInfo(param.getDestId()));

        return ApiResult.success(json);
    }

    @ApiOperation("关注用户")
    @PostMapping("/focus")
    public ApiResult<Object> focus(@RequestBody @Valid UserFocusParam param) {
        if (param.getDestId().equals(param.getUserId()))
        {
            return ApiResult.failed(10, "不能关注自己");
        }
        
        if (param.getAction() == Constant.USER_ACTION_CANCEL) {
            // 取消关注
            userService.cancelFocus(param.getUserId(), param.getDestId());
        }
        else {
            // 关注
            userService.attachFocus(param.getUserId(), param.getDestId());
        }

        return ApiResult.success();
    }

    @ApiOperation("设置用户信息")
    @PostMapping("/setUserInfo")
    public ApiResult<Object> setUserInfo(@RequestBody @Valid UserSetUserInfoParam param) {
        UserBaseInfo userInfo  = param.getUserInfo();
        int infoStatus  = userInfo.getInfoStatus();
        boolean update  = false;


        if (param.getSex() != null)
        {
            update  = true;
            
            userInfo.setSex(param.getSex());
        }

        if ((param.getHeadUri() != null) && (!param.getHeadUri().equals(userInfo.getHeadUri())))
        {
            //有头像待审不允许修改头像
            if ((infoStatus & Constant.INFO_STATUS_HEAD) == 0)
            {
                //已认证用户修改头像保存为形象照待审，始终人审
                if (userInfo.getAuthRole() > 0)
                {
                    userInfo.setInfoStatus(userInfo.getInfoStatus() | Constant.INFO_STATUS_HEAD);
                    userService.saveAuditInfo(Constant.AUDIT_TYPE_PORTRAIT, param.getUserId(), param.getHeadUri(), Constant.AUDIT_STATUS_WAIT);

                    SmsUtils.sendManageNotice("用户头像待审");
                }
                else
                {
                    //先机审，机审不过再人审
                    int ret  = Moderation.checkImage("user/" + param.getUserId() + "/" + param.getHeadUri());
                    if (ret < 0)
                    {
                        userInfo.setInfoStatus(userInfo.getInfoStatus() | Constant.INFO_STATUS_HEAD);
                        albumService.saveImage(param.getUserId(), param.getHeadUri(), Constant.AUDIT_TYPE_PORTRAIT, Constant.AUDIT_STATUS_WAIT);

                        SmsUtils.sendManageNotice("用户头像待审");
                    }
                    else
                    {
                        //删除旧头像
                        if (userInfo.getHeadUri() != null)
                        {
                            CloudStorage.deleteUserFile(param.getUserId(), userInfo.getHeadUri());
                        }
                        //设置新头像
                        userInfo.setHeadUri(param.getHeadUri());

                        ChatPrivateData data  = new ChatPrivateData();
                        data.setContent("尊敬的用户，您修改的头像已审核通过。");
                        messageService.sendUserMessage(Constant.USERID_SYSTEM, param.getUserId(), Constant.MSG_TYPE_TEXT, data, false);                
                    }
                }

                update  = true;
            }
            else
            {
                //删除上传的云存文件
                CloudStorage.deleteUserFile(param.getUserId(), param.getHeadUri());

                ChatPrivateData data  = new ChatPrivateData();
                data.setContent("尊敬的用户，因为您已有头像等待审核，所以本次修改未能成功，请等待审核完成后再重新修改。谢谢您的理解和支持。");
                messageService.sendUserMessage(Constant.USERID_SYSTEM, param.getUserId(), Constant.MSG_TYPE_TEXT, data, false);
            }
        }

        if ((param.getNickName() != null) && ((infoStatus & Constant.INFO_STATUS_NAME) == 0))
        {
            String nickName  = param.getNickName().trim();
            //先机审，机审不过再人审
            int ret  = Moderation.checkText(nickName);
            if (ret < 0)
            {
                userInfo.setInfoStatus(userInfo.getInfoStatus() | Constant.INFO_STATUS_NAME);
                userService.saveAuditInfo(Constant.AUDIT_TYPE_NICKNAME, param.getUserId(), nickName, Constant.AUDIT_STATUS_WAIT);

                SmsUtils.sendManageNotice("用户昵称待审");
            }
            else
            {
                userInfo.setNickName(nickName);

                ChatPrivateData data  = new ChatPrivateData();
                data.setContent("尊敬的用户，您修改的昵称已审核通过。");
                messageService.sendUserMessage(Constant.USERID_SYSTEM, param.getUserId(), Constant.MSG_TYPE_TEXT, data, false);                   
            }

            update  = true;
        }

        if (update == true)
        {
            int ret  = userService.saveUserBaseInfo(userInfo);
            if (ret < 0)
            {
                return ApiResult.failed(ApiCodeEnum.SERVICE_ERROR);
            }

            if ((param.getSex() != null) && (userInfo.getHeadUri() != null))
            {
                JSONObject json  = new JSONObject();
                json.set("sex", param.getSex());
                json.set("userId", userInfo.getUserId());

                HttpUtils.send_post_request("http://localhost:8183/kmsg/userRegister.php", null, JSONUtil.toJsonStr(json));            
            }
        }

        //更新用户扩展信息
        if (param.getExtInfo() != null)
        {
            UserExtendInfo oldInfo  = userService.getUserExtendInfo(param.getUserId());
            JSONObject json  = JSONUtil.parseObj(param.getExtInfo());

            if (json.getStr("slogan") != null)
            {
                //有个人签名待审不允许修改个人签名
                if ((infoStatus & Constant.INFO_STATUS_HEAD) == 0)
                {
                    String slogan  = json.getStr("slogan");
                    int ret  = Moderation.checkText(slogan);
                    if (ret == 0)
                    {
                        ChatPrivateData data  = new ChatPrivateData();
                        data.setContent("尊敬的用户，您修改的个人签名已审核通过。");
                        messageService.sendUserMessage(Constant.USERID_SYSTEM, param.getUserId(), Constant.MSG_TYPE_TEXT, data, false);                      
                    }
                    else
                    {
                        json.remove("slogan");
                        userService.saveAuditInfo(Constant.AUDIT_TYPE_SLOGAN, userInfo.getUserId(), slogan, Constant.AUDIT_STATUS_WAIT);

                        SmsUtils.sendManageNotice("用户个人签名待审");
                    }
                }
                else
                {
                    json.remove("slogan");

                    ChatPrivateData data  = new ChatPrivateData();
                    data.setContent("尊敬的用户，因为您已有个人签名等待审核，所以本次修改未能成功，请等待审核完成后再重新修改。谢谢您的理解和支持。");
                    messageService.sendUserMessage(Constant.USERID_SYSTEM, param.getUserId(), Constant.MSG_TYPE_TEXT, data, false);
                }                
            }

            if (json.getStr("voice") != null)
            {
                String voice  = json.getStr("voice");
                int ret  = Moderation.checkAudio("user/" + userInfo.getUserId() + "/" + voice);
                if (ret == 0)
                {
                    ChatPrivateData data  = new ChatPrivateData();
                    data.setContent("尊敬的用户，您的语音名片已审核通过。");
                    messageService.sendUserMessage(Constant.USERID_SYSTEM, param.getUserId(), Constant.MSG_TYPE_TEXT, data, false);     
                }
                else
                {
                    json.remove("voice");
                    userService.saveAuditInfo(Constant.AUDIT_TYPE_VOICE, userInfo.getUserId(), voice, Constant.AUDIT_STATUS_WAIT);

                    SmsUtils.sendManageNotice("用户语音名片待审");
                }
            }

            if (json.size() > 0)
            {
                UserExtendInfo extInfo;
                UserExtendInfo newInfo  = new UserExtendInfo();           
                BeanUtil.copyProperties(json, newInfo);

                if (oldInfo == null)
                {
                    newInfo.setUserId(param.getUserId());
                    newInfo.setCreateTime(TimeUtils.getTimeSecond());

                    extInfo  = newInfo;
                }
                else
                {
                    // 更新非空字段
                    BeanUtil.copyProperties(newInfo, oldInfo, 
                        CopyOptions.create()
                            .setIgnoreNullValue(true)
                            .setIgnoreProperties("userId"));
                            
                    extInfo  = oldInfo;
                }

                userService.saveUserExtendInfo(extInfo);
            }
        }

        return ApiResult.success("提交成功，请等待审核");
    }

    @ApiOperation("通话设置")
    @PostMapping("/callSetting")
    public ApiResult<Object> callSetting(@RequestBody @Valid UserCallSettingParam param) {
        UserBaseInfo userInfo  = param.getUserInfo();
        if (userInfo == null)
        {
            return ApiResult.failed(10, "用户信息有误");
        }

        boolean update  = false;
        if (param.getAudioPrice() != null)
        {
            int maxPrice  = (userInfo.getAuthLevel() + 1) * 100;
            if (param.getAudioPrice() > maxPrice)
            {
                ChatPrivateData data;
                data  = new ChatPrivateData();
                data.setContent("您当前的等级通话单价最高只能设置为" + maxPrice + "，升级后才能设置更高价格");
                messageService.sendSystemMessage(userInfo.getUserId(), Constant.MSG_TYPE_TEXT, data); 
                
                return ApiResult.failed(10, "设置失败");
            } 

            userInfo.setAudioPrice((param.getAudioPrice() / 10) * 10);

            update  = true;
        }

        if ((userInfo.getAuthRole() > 0) && (param.getIsRefuse() != null) && (!param.getIsRefuse().equals(userInfo.getIsRefuse())))
        {
            userInfo.setIsRefuse(param.getIsRefuse());

            //修改勿扰模式时更新用户在线活跃时间
            JSONObject json  = new JSONObject();
            json.set("time", TimeUtils.getTimeSecond());
            json.set("userId", param.getUserId());
            json.set("type", (param.getIsRefuse() == Constant.ENABLE_YES) ? 101 : 100);
            HttpUtils.send_post_request("http://localhost:8183/scoreAward/onlineAward/setAliveTime.php", null, JSONUtil.toJsonStr(json));                

            update  = true;
        }

        if (update == true)
        {
            int ret  = userService.saveUserBaseInfo(userInfo);
            if (ret < 0)
            {
                return ApiResult.failed(ApiCodeEnum.SERVICE_ERROR);
            }
        }

        return ApiResult.success();
    }

    @ApiOperation("用户认证")
    @PostMapping("/auth")
    public ApiResult<Object> auth(@RequestBody @Valid UserAuthParam param) {
        UserBaseInfo userInfo = param.getUserInfo();
        if (userInfo.getType() == Constant.ACCOUNT_TYPE_KEFU)
        {
            return ApiResult.failed(10, "无权限");
        }

        //资料审核中
        if (userService.getAuthStatus(userInfo) == Constant.AUTH_STATUS_WAIT)
        {
            return ApiResult.failed(10, "资料审核中，请勿重复提交");
        }

        //已审核通过
        if (userService.getAuthStatus(userInfo) == Constant.AUTH_STATUS_PASS)
        {
            return ApiResult.failed(10, "已认证成功，无需认证");
        }

        if (param.getHeadUri() != null)
        {
            //认证倾听者必须重新上传头像，自动拒绝所有待审头像
            userService.refuseHeadAudit(param.getUserId());
            //即使上传的头像与原头像相同也需要审核，因为有可能之前的头像不符合认证要求
            userService.saveAuditInfo(Constant.AUDIT_TYPE_PORTRAIT, param.getUserId(), param.getHeadUri(), Constant.AUDIT_STATUS_WAIT);
            //形象照会替换为头像，所以要把头像也设为待审
            userInfo.setInfoStatus(userInfo.getInfoStatus() | Constant.INFO_STATUS_HEAD);
        }

        if (param.getPhotos() != null)
        {
            JSONArray json  = JSONUtil.parseArray(param.getPhotos());
            for (Object photo : json)
            {
                userService.saveAuditInfo(Constant.AUDIT_TYPE_PHOTO, param.getUserId(), (String)photo, Constant.AUDIT_STATUS_WAIT);
            }
        }

        if (param.getVideo() != null)
        {
            userService.saveAuditInfo(Constant.AUDIT_TYPE_VIDEO, param.getUserId(), param.getVideo(), Constant.AUDIT_STATUS_WAIT);
        }

        if (param.getExtInfo() != null)
        {
            JSONObject json  = JSONUtil.parseObj(param.getExtInfo());
            UserExtendInfo extend  = BeanUtil.copyProperties(json, UserExtendInfo.class);

            if (extend.getSlogan() != null)
            {
                userService.saveAuditInfo(Constant.AUDIT_TYPE_SLOGAN, userInfo.getUserId(), extend.getSlogan().trim(), Constant.AUDIT_STATUS_WAIT);
            }

            if (extend.getVoice() != null)
            {
                userService.saveAuditInfo(Constant.AUDIT_TYPE_VOICE, userInfo.getUserId(), extend.getVoice(), Constant.AUDIT_STATUS_WAIT);
            }
        }
        
        //更新用户信息
        userInfo.setInfoStatus(userInfo.getInfoStatus() | Constant.INFO_STATUS_AUTH);
        userService.saveUserBaseInfo(userInfo);

        //发送短信通知
        SmsUtils.sendManageNotice("用户" + param.getUserId() + "申请认证");

        return ApiResult.success("提交成功，请等待审核");
    }

    @ApiOperation("获取关注用户列表")
    @PostMapping("/getFocusList")
    public ApiResult<Object> getFocusList(@RequestBody @Valid UserGetFocusListParam param) {
        JSONObject json  = new JSONObject();
        json.set("userList", userService.getFocusList(param.getUserId(), param.getStartId()));

        return ApiResult.success(json);
    }

    @ApiOperation("屏蔽用户")
    @PostMapping("/block")
    public ApiResult<Object> block(@RequestBody @Valid UserBlockParam param) {
        if (param.getDestId().equals(param.getUserId()))
        {
            return ApiResult.failed(10, "不能屏蔽自己");
        }
        
        if (param.getAction() == Constant.USER_ACTION_CANCEL)
        {
            // 取消屏蔽
            userService.cancelBlock(param.getUserId(), param.getDestId());
        }
        else
        {
            // 取消关注
            userService.cancelFocus(param.getUserId(), param.getDestId());
            // 屏蔽
            userService.attachBlock(param.getUserId(), param.getDestId());
        }

        return ApiResult.success();
    }

    @ApiOperation("获取认证信息")
    @PostMapping("/getAuthInfo")
    public ApiResult<Object> getAuthInfo(@RequestBody @Valid AuthParam param) {
        JSONObject json  = new JSONObject();
        UserBaseInfo userInfo  = param.getUserInfo();
        if (userInfo.getAuthRole() > 0)
        {
            json.set("authStatus", 0);
            json.set("infoStatus", Constant.AUTH_STATUS_PASS);
            json.set("photoNum", 0);

            return ApiResult.success(json);
        }

        List<UserAuthInfo> infos  = userService.getAuthInfoByStatus(Constant.AUDIT_STATUS_WAIT, param.getUserId());
        if (infos.size() > 0)
        {
            json.set("authStatus", 0);
            json.set("infoStatus", Constant.AUTH_STATUS_WAIT);
            json.set("photoNum", 0);

            return ApiResult.success(json);
        }

        //根据已认证的信息返回需要增补的认证信息
        int infoStatus  = Constant.AUTH_STATUS_NONE;
        int authStatus  = userInfo.getAuthStatus();
        //认证信息都通过，并且相册中审核通过的照片个数大于等于3，则表示认证通过（因为authStatus中没有记录生活照的审核状态，所以要单独判断）
        List<UserAlbumInfo> photos  = albumService.getPhotosByUser(param.getUserId(), 0);

        json.set("authStatus", authStatus);
        json.set("infoStatus", infoStatus);
        json.set("photoNum", photos.size());

        return ApiResult.success(json);
    }

    @ApiOperation("用户主页")
    @PostMapping("/home")
    public ApiResult<Object> home(@RequestBody @Valid UserGetUserInfoParam param) {
        Object userInfo;
        //游客模式
        if (param.getUserId() == null)
        {
            userInfo  = userService.getUserById(param.getDestId());
        }
        else
        {
            userInfo  = userService.getUserByIdWithFocus(param.getDestId(), param.getUserId());
        }
        
        if (userInfo == null)
        {
            return ApiResult.failed(10, "用户信息有误");
        }

        JSONObject json  = new JSONObject();
        json.set("baseInfo", BeanUtil.copyProperties(userInfo, UserInfoVO.class));
        json.set("extInfo", userService.getUserExtendInfo(param.getDestId()));
        json.set("album", albumService.getPhotosByUser(param.getDestId(), 0));
        json.set("video", videoService.getUserVideos(param.getDestId(), 0));

        return ApiResult.success(json);
    }

    @ApiOperation("聊主中心")
    @PostMapping("/hostCenter")
    public ApiResult<Object> hostCenter(@RequestBody @Valid AuthParam param) {
        int withDrawRatio  = 0;

        //先更新接通率
        UserBaseInfo userInfo  = param.getUserInfo();
        userService.updateListenerInfo(userInfo);
        //设置提现比例
        if ((TimeUtils.getTimeSecond() - userInfo.getCreateTime()) < 2592000)
        {
            withDrawRatio  = 80;
        }
        else
        {
            switch (userInfo.getAuthLevel())
            {
                case 1:
                {
                    withDrawRatio  = 50;
                    break;
                }
                case 2:
                {
                    withDrawRatio  = 60;
                    break;
                }
                case 3:
                {
                    withDrawRatio  = 70;
                    break;
                }
                case 4:
                {
                    withDrawRatio  = 80;
                    break;
                }
                default:
                {
                    withDrawRatio  = 40;
                    break;
                }
            }
        }

        JSONObject json  = new JSONObject();
        json.set("withDrawRatio", withDrawRatio);

        return ApiResult.success(json);
    }

    @ApiOperation("设置关注")
    @PostMapping("/setFocus")
    public ApiResult<Object> setFocus(@RequestBody @Valid UserFocusParam param) {
        if (param.getDestId().equals(param.getUserId()))
        {
            return ApiResult.failed(10, "不能关注自己");
        }
        
        userService.setFocus(param.getUserId(), param.getDestId(), param.getAction());

        return ApiResult.success();
    }

    @ApiOperation("设置好友")
    @PostMapping("/setFriend")
    public ApiResult<Object> setFriend(@RequestBody @Valid UserSetFriendParam param) {
        if (Constant.USER_ACTION_REQUEST == param.getAction())
        {
            UserFansInfo info  = userService.queryFocusByUser(param.getUserId(), param.getDestId());
            if (ChronoUnit.DAYS.between(info.getUpdateTime(), TimeUtils.getLocalDateTime()) < 3)
            {
                return ApiResult.failed(10, "关注三天后才能加好友");
            }

            int ret  = chatService.getMessageStatis(param.getUserId(), param.getDestId());
            if (ret < 70)
            {
                return ApiResult.failed(10, "热度不够还不能加好友");
            }
        }

        userService.setFriend(param.getUserId(), param.getDestId(), param.getAction());

        return ApiResult.success();
    }

    @ApiOperation("获取好友列表")
    @PostMapping("/getFriendList")
    public ApiResult<Object> getFriendList(@RequestBody @Valid UserGetFriendListParam param) {
        JSONObject json  = new JSONObject();
        json.set("userList", userService.getFriendList(param.getUserId(), param.getStartId()));      

        return ApiResult.success(json);
    }
}
